home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ddj9304.zip / STEREO.ZIP / LISTING2.C < prev   
INI File  |  1993-01-19  |  21KB  |  521 lines

  1. [LISTING2.C]
  2.  
  3. /* Created by Victor J. Duvanenko  11-05-90
  4.  
  5.     Program to display the Scanning Tunneling Microscope (STM)
  6.     collected image data in 'true' 3-D.
  7.  
  8. -------------------------------------------------------------------*/
  9.  
  10. #include <math.h>
  11. #include <float.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14.  
  15. #define BOOLEAN     int
  16. #define TRUE          1
  17. #define FALSE         0
  18. #define OK            0
  19. #define NOT_OK       -1
  20. #define ACCEPT        TRUE
  21. #define REJECT        FALSE
  22. #define WHITE         1
  23. #define PI            3.1415926
  24. #define INTEROCULAR_DISTANCE   2.5           /* inches */
  25. #define PIXEL_WIDTH            0.021         /* inches */
  26. #define LEFT_EYE         0
  27. #define RIGHT_EYE        1
  28. #define NUM_DIMENSIONS   3
  29. #define NUM_SHADES     256
  30. #define SCREEN_HEIGHT  512
  31. #define SCREEN_WIDTH   640
  32. #define WINDOW_BORDER_WIDTH   3
  33. #define PARALLEL      0
  34. #define PERSPECTIVE   1
  35. #define    NUM_LINES   348              /* for an IBM PC Hercules display */
  36. #define MAX_IMAGE_SIZE   200         /* 400 x 400 samples */
  37.  
  38. #define MALLOC(x)  ((x *) malloc( sizeof(x)))
  39. #define ROUND(x)   ((x) > 0.0  ?  (int)((x) + 0.5) : (int)((x) - 0.5))
  40. #define MAX(A, B)  ((A) > (B)  ?  (A) : (B))
  41. #define MIN(A, B)  ((A) < (B)  ?  (A) : (B))
  42.  
  43. #define DEBUG      FALSE        /* en(dis)able debug sections */
  44. #define DRAW        TRUE
  45. #define LEX         TRUE
  46. #define PC         FALSE
  47.  
  48. struct    point_3D
  49. {
  50.     float  x, y, z;
  51. };
  52. typedef    struct    point_3D    point_3D_t;
  53.  
  54. struct    point_3D_ex
  55. {
  56.     float   x, y, z;
  57.     float   sha, shb;        /* shading values for triangle A and B */
  58. };
  59. typedef    struct    point_3D_ex    point_3D_ex_t;
  60.  
  61. /* STM data file header parameters. */
  62. int num_samples;        /* number of samples per scan line */
  63. int log_input;          /* 0 - linear input; 1 - logarithmic input */
  64. float z_scale;          /* vertical scale */
  65. float scan_sz;          /* 0 < X, Y < scan_sz in nm */
  66.  
  67. point_3D_t  min, max;   /* min and max of the input/STM data */
  68.  
  69. /* X, Y, Z values at each sample point - STM gives the Z; X & Y are deduced
  70.    from the stepping distance (sampling distance => (scan_sz / num_samples)).*/
  71. point_3D_ex_t  image[ MAX_IMAGE_SIZE ][ MAX_IMAGE_SIZE ];
  72.  
  73. /* Transformed image */
  74. point_3D_ex_t  tr_image[ MAX_IMAGE_SIZE ][ MAX_IMAGE_SIZE ];
  75.  
  76. #if Z_BUFFER
  77. /* Image buffer */
  78. unsigned char b_image[ SCREEN_WIDTH ][ SCREEN_HEIGHT ];
  79. float z_buffer[ SCREEN_WIDTH ][ SCREEN_HEIGHT ];
  80. #endif
  81.  
  82. /* World window/volume rectangle boundaries - accessable to all routines */
  83. double  y_bottom, y_top, x_right, x_left, z_front, z_back;
  84. double  y_bottom_d, y_top_d, x_right_d, x_left_d, z_front_d, z_back_d;
  85.  
  86. point_3D_t  light_source;        /* light source direction unit vector */
  87. point_3D_t  eye_pt;              /* viewer eye point in world coordinates */
  88. point_3D_t  vpn;                 /* view plane normal vector */
  89. point_3D_t  vup;                 /* view up vector */
  90. double  Tm[ 4 ][ 4 ];            /* transformation matrix */
  91. double  proj_plane;              /* perspective projection plane on -Z-axis */
  92.  
  93. /* some global variables */
  94. int  f_color;
  95.  
  96. /* External functions */
  97. extern  void set_clip_volume( double, double, double, double, double, double );
  98. extern       find_object_center( double *, double *, double *, int );
  99. extern  void read_stm_database();
  100. extern  void draw_clip_window();
  101. extern       matrix_mult( double *, int, int, double *, int, int, double * );
  102.  
  103. /*-------------------------------------------------------------------
  104.   Procedure that creates a composite viewing transformation matrix
  105.   in accordance with p. 258 - 261 of 1st ed. of F & vD.
  106.   The viewer eye point will be moved to the origin looking down the
  107.   negative Z-axis with the view up vector in the yz-plane in positive
  108.   y half of the plane (pointing up).
  109.   P1 = VRP = eye_pt
  110.   P2 = origin
  111.   P3 = P1 + vup
  112.   This procedure is executed only once and only when the viewer eye
  113.   point position changes.
  114. ---------------------------------------------------------------------*/
  115. make_composite_viewing_matrix( proj )
  116. int proj;      /* PARALLEL or PERSPECTIVE */
  117. {
  118.    double p1[4], p2[4], p3[4], p_tmp[4];
  119.    double T[4][4], Rx[4][4], Ry[4][4], Rz[4][4], C_tmp1[4][4], C_tmp2[4][4];
  120.    double Per[4][4], d1, d2, d12, cos_ang, sin_ang;
  121.  
  122.    /* Initialize the three points */
  123.    p1[0] = eye_pt.x;  p1[1] = eye_pt.y;  p1[2] = eye_pt.z;  p1[3] = 1.0;
  124.    p2[0] = p2[1] = p2[2] = 0.0;  p2[3] = 1.0;
  125.    p3[0] = p1[0] + vup.x;  p3[1] = p1[1] + vup.y;  p3[2] = p1[2] + vup.z;
  126.                            p3[3] = 1.0;
  127.    /* Magnitude of vector p1->p2 */
  128.    d12 = sqrt( p1[0] * p1[0] + p1[1] * p1[1] + p1[2] * p1[2] );
  129.  
  130.    /* Create the translation matrix. */
  131.    set_to_identity( T, 4 );
  132.    T[3][0] = -p1[0];   T[3][1] = -p1[1];   T[3][2] = -p1[2];
  133.  
  134.    /* Translate the three points p1, p2, and p3 to the origin. */
  135.    matrix_mult( p1, 1, 4, T, 4, 4, p_tmp );
  136.    copy_matrix( p_tmp, p1, 1, 4 );
  137.    matrix_mult( p2, 1, 4, T, 4, 4, p_tmp );
  138.    copy_matrix( p_tmp, p2, 1, 4 );
  139.    matrix_mult( p3, 1, 4, T, 4, 4, p_tmp );
  140.    copy_matrix( p_tmp, p3, 1, 4 );
  141.  
  142.    d1 = sqrt( p2[0] * p2[0] + p2[2] * p2[2] );      /* length of projection */
  143.    cos_ang = -p2[2] / d1;
  144.    sin_ang =  p2[0] / d1;
  145.  
  146.    /* Create the rotation about Y-axis matrix. */
  147.    set_to_identity( Ry, 4 );
  148.    Ry[0][0] = cos_ang;  Ry[0][2] = -sin_ang;
  149.    Ry[2][0] = sin_ang;  Ry[2][2] =  cos_ang;
  150.  
  151.    /* Rotate the three points p2, and p3 about the Y-axis. */
  152.    /* p1 is at the origin after translation => no need to rotate. */
  153.    matrix_mult( p2, 1, 4, Ry, 4, 4, p_tmp );
  154.    copy_matrix( p_tmp, p2, 1, 4 );
  155.    matrix_mult( p3, 1, 4, Ry, 4, 4, p_tmp );
  156.    copy_matrix( p_tmp, p3, 1, 4 );
  157.  
  158.    cos_ang = -p2[2] / d12;
  159.    sin_ang = -p2[1] / d12;
  160.  
  161.    /* Create the rotation about X-axis matrix. */
  162.    set_to_identity( Rx, 4 );
  163.    Rx[1][1] = cos_ang;   Rx[1][2] = sin_ang;
  164.    Rx[2][1] = -sin_ang;  Rx[2][2] = cos_ang;
  165.  
  166.    /* Rotate the three points p2, and p3 about the X-axis. */
  167.    matrix_mult( p2, 1, 4, Rx, 4, 4, p_tmp );
  168.    copy_matrix( p_tmp, p2, 1, 4 );
  169.    matrix_mult( p3, 1, 4, Rx, 4, 4, p_tmp );
  170.    copy_matrix( p_tmp, p3, 1, 4 );
  171.  
  172.    /* Sanity check. */
  173.    printf( "The view vector should be [ %lf %lf %lf %lf ]\n", 0.0, 0.0, -d12,
  174.                                                               1.0 );
  175.    printf( "The view vector is [ %lf %lf %lf %lf ]\n", p2[0], p2[1],
  176.                                                        p2[2], p2[3] );
  177.  
  178.    d2 = sqrt( p3[0] * p3[0] + p3[1] * p3[1] );
  179.    cos_ang = p3[1] / d2;
  180.    sin_ang = p3[0] / d2;
  181.  
  182.    /* Create the rotation about Z-axis matrix. */
  183.    set_to_identity( Rz, 4 );
  184.    Rz[0][0] = cos_ang;   Rz[0][1] = sin_ang;
  185.    Rz[1][0] = -sin_ang;  Rz[1][1] = cos_ang;
  186.  
  187.    /* At this point the translation, and all rotation matrices are known
  188.       and need to be combined into a single transformaation matrix. */
  189.    matrix_mult( T, 4, 4, Ry, 4, 4, C_tmp1 );
  190.    matrix_mult( C_tmp1, 4, 4, Rx, 4, 4, C_tmp2 );
  191.    matrix_mult( C_tmp2, 4, 4, Rz, 4, 4, C_tmp1 );
  192.  
  193.    copy_matrix( C_tmp1, Tm, 4, 4 );
  194. }
  195. /*-------------------------------------------------------------------
  196.   Procedure that prints the main menu of operations available to a user.
  197. ---------------------------------------------------------------------*/
  198. void print_menu()
  199. {
  200.     printf( "Load STM database ...........................(1)\n" );
  201.     printf( "Set light source direction vector ...........(2)\n" );
  202.     printf( "Set viewer reference point ..................(3)\n" );
  203.     printf( "Set view up vector ..........................(4)\n" );
  204.     printf( "Display with    parallel projection .........(5)\n" );
  205.     printf( "Display with perspective projection .........(6)\n" );
  206.     printf( "Set perspective projection plane ............(7)\n" );
  207.     printf( "Set window limits ...........................(8)\n" );
  208.     printf( "Set viewport limits .........................(9)\n" );
  209.     printf( "Display in stereo ..........................(10)\n" );
  210.     printf( "Quit........................................(26)\n" );
  211.     printf( "? " );
  212. }
  213. /* Procedure to transform the image by a transformation matrix.
  214.    Assumes the matrix (m) is a 4x4 matrix.  The result is homogenized
  215.    (divided by W) as well.  The source and destination can be the same
  216.    array.  */
  217. transform_and_homogenize_image( s, d, tm )
  218. point_3D_ex_t  s[][ MAX_IMAGE_SIZE ], d[][ MAX_IMAGE_SIZE ];
  219. double *tm;         /* transformation matrix */
  220. {
  221.    register i, j;
  222.    int  num_lines;
  223.    double  p[4];      /* the point to be transformed */
  224.    double  t[4], inv_W;
  225.  
  226.    num_lines = MIN( num_samples, MAX_IMAGE_SIZE );
  227.    for( i = 0; i < num_lines; i++ )
  228.       for( j = 0; j < num_lines; j++ )
  229.       {
  230.          p[0] = s[i][j].x;   p[1] = s[i][j].y;
  231.          p[2] = s[i][j].z;   p[3] = 1.0;
  232.          matrix_mult( p, 1, 4, tm, 4, 4, t );
  233.          if ( t[3] != 1.0 )        /* divide by W (homogenize) */
  234.          {
  235.             inv_W = 1.0 / t[3];
  236.             t[0] *= inv_W;   t[1] *= inv_W;  t[2] *= inv_W;
  237.          }
  238.          d[i][j].x = t[0];   d[i][j].y = t[1];   d[i][j].z = t[2];
  239.          d[i][j].sha = s[i][j].sha;    d[i][j].shb = s[i][j].shb;
  240.       }
  241. }
  242. /* Procedure to render the transformed image. */
  243. render_image( y )
  244. int  y;
  245. {
  246.    register i, j;
  247.    int    num_lines;
  248.    short  v[6], intensity;
  249.  
  250.    num_lines = MIN( num_samples, MAX_IMAGE_SIZE );
  251.    num_lines--;
  252.    for( i = 0; i < num_lines; i++ )
  253.       for( j = 0; j < num_lines; j++ )
  254.       {
  255.          v[0] = ROUND( tr_image[ i     ][ j     ].x );
  256.          v[1] = ROUND( tr_image[ i     ][ j     ].y );
  257.          v[2] = ROUND( tr_image[ i + 1 ][ j     ].x );
  258.          v[3] = ROUND( tr_image[ i + 1 ][ j     ].y );
  259.          v[4] = ROUND( tr_image[ i + 1 ][ j + 1 ].x );
  260.          v[5] = ROUND( tr_image[ i + 1 ][ j + 1 ].y );
  261.          /* Render triangle A */
  262.          intensity = ROUND( tr_image[ i ][ j ].sha * (double)(NUM_SHADES - 1));
  263.          if ( intensity > ( NUM_SHADES - 1 ))
  264.             intensity = NUM_SHADES - 1;      /* saturate */
  265.          if ( intensity < 0 )
  266.          {
  267. #if 0
  268.             printf( "Triangle A,  intensity = %d\n", intensity );
  269.             printf( "v11.x = %f, v11.y = %f, v11.z = %f\n",
  270.                     image[i][j].x, image[i][j].y, image[i][j].z );
  271.             printf( "v21.x = %f, v21.y = %f, v21.z = %f\n",
  272.                     image[i+1][j].x, image[i+1][j].y, image[i+1][j].z );
  273.             printf( "v22.x = %f, v22.y = %f, v22.z = %f\n",
  274.                     image[i+1][j+1].x, image[i+1][j+1].y, image[i+1][j+1].z );
  275. #endif
  276.             intensity = 0;
  277.          }
  278.          if ( clip_to_viewport( v, 6, y ) == ACCEPT )
  279.             dspoly( &intensity, v, &6 );
  280.  
  281.          v[2] = ROUND( tr_image[ i     ][ j + 1 ].x );
  282.          v[3] = ROUND( tr_image[ i     ][ j + 1 ].y );
  283.          /* Render triangle B */
  284.          intensity = ROUND( tr_image[ i ][ j ].shb * (double)( NUM_SHADES - 1));
  285.          if ( intensity > ( NUM_SHADES - 1 ))
  286.             intensity = NUM_SHADES - 1;      /* saturate */
  287.          if ( intensity < 0 )   intensity = 0;
  288.          if ( clip_to_viewport( v, 6, y ) == ACCEPT )
  289.             dspoly( &intensity, v, &6 );
  290.       }
  291. }
  292. /* Procedure to display the database with a projection. */
  293. display_3D_data( proj )
  294. int proj;
  295. {
  296.    double  Tw[4][4], S[4][4], Td[4][4], Ry[4][4], Per[4][4], tmp[4][4];
  297.    double  Left[4][4], Right[4][4];
  298.    double  e_v,      /* interocular distance mapped back to the view  coord. */
  299.            e_w;      /* interocular distance mapped back to the world coord. */
  300.  
  301.    printf( "Computing normals for shading.  " );
  302.    compute_normals();      /* and the dot products for each triangle */
  303.    printf( "Done.\n" );
  304.  
  305.    /* Perspective projection must use three steps:
  306.       1)  Compute normals and project,
  307.       2)  Divide by W (homogenize)
  308.       3)  Transform into the device coordinates. */
  309.    if ( proj == PERSPECTIVE )
  310.    {
  311.       /* map the physical interocular distance into the view port coordinates. */
  312.       e_v = INTEROCULAR_DISTANCE / PIXEL_WIDTH;      /* e_v == pixels */
  313.       /* map from the viewport coordinate system to the world. */
  314.       e_w = e_v / (( x_right_d - x_left_d ) / ( x_right - x_left ));
  315.  
  316.       set_to_identity( Left,  4 );
  317.       set_to_identity( Right, 4 );
  318.  
  319.       /* Use the Translate, Project, Translate back model. */
  320.  
  321.       /* Create the Left eye transformation matrix. */
  322.       set_to_identity( Tw, 4 );    /* translate the left eye to the origin */
  323.       Tw[3][0] = -e_w / 2.0;
  324.       matrix_mult( Left, 4, 4, Tw, 4, 4, tmp );
  325.  
  326.       /* Create the perspective projection matrix. */
  327.       set_to_identity( Per, 4 );
  328.       Per[2][3] = 1.0 / proj_plane;          /* 1/d */
  329.       Per[3][3] = 0.0;
  330.       matrix_mult( tmp, 4, 4, Per, 4, 4, Left );
  331.  
  332.       Tw[3][0] = e_w / 2.0;             /* translate back */
  333.       matrix_mult( Left, 4, 4, Tw, 4, 4, tmp );
  334.       copy_matrix( tmp, Left, 4, 4 );
  335.  
  336.       /* Create the Right eye transformation matrix. */
  337.       set_to_identity( Tw, 4 );    /* translate the right eye to the origin */
  338.       Tw[3][0] = e_w / 2.0;
  339.       matrix_mult( Right, 4, 4, Tw, 4, 4, tmp );
  340.  
  341.       /* Create the perspective projection matrix. */
  342.       set_to_identity( Per, 4 );
  343.       Per[2][3] = 1.0 / proj_plane;          /* 1/d */
  344.       Per[3][3] = 0.0;
  345.       matrix_mult( tmp, 4, 4, Per, 4, 4, Right );
  346.  
  347.       Tw[3][0] = -e_w / 2.0;             /* translate back */
  348.       matrix_mult( Right, 4, 4, Tw, 4, 4, tmp );
  349.       copy_matrix( tmp, Right, 4, 4 );
  350.  
  351. #if 0
  352.       printf( "Transforming, projecting and homogenizing the image.  " );
  353.       transform_and_homogenize_image( image, tr_image, Tm );
  354.       printf( "Done.\n" );
  355. #endif
  356.    }
  357.  
  358.    /* Create the world to device transformation matrix. */
  359.  
  360.    /* Create the translation matrix. Translate only in X and Y. */
  361.    set_to_identity( Tw, 4 );
  362.    Tw[3][0] = -x_left;   Tw[3][1] = -y_bottom;   Tw[3][2] = 0.0;
  363.  
  364.    /* Create a uniform scale matrix. */
  365.    set_to_identity( S, 4 );
  366.    S[0][0] = ( x_right_d - x_left_d   ) / ( x_right - x_left   );
  367.    S[1][1] = ( y_top_d   - y_bottom_d ) / ( y_top   - y_bottom );
  368.    S[2][2] = ( z_back_d  - z_front_d  ) / ( z_back  - z_front  );
  369.  
  370.    matrix_mult( Tw, 4, 4, S, 4, 4, tmp );
  371.    copy_matrix( tmp, Tw, 4, 4 );
  372.  
  373.    /* Create the translation matrix. Translate only in X and Y. */
  374.    set_to_identity( Td, 4 );
  375.    Td[3][0] = x_left_d;   Td[3][1] = y_bottom_d;   Td[3][2] = 0.0;
  376.  
  377.    matrix_mult( Tw, 4, 4, Td, 4, 4, tmp );
  378.    copy_matrix( tmp, Tw, 4, 4 );
  379.  
  380.    /* Since the device/screen origin on the LEX/90 is in the upper left
  381.       we nee to reflect the Y and translate by the
  382.       screen height to place the device origin in the bottom left. */
  383.    set_to_identity( Ry, 4 );
  384.    Ry[1][1] = -1.0;
  385.    matrix_mult( Tw, 4, 4, Ry, 4, 4, tmp );
  386.    copy_matrix( tmp, Tw, 4, 4 );
  387.  
  388.    set_to_identity( Td, 4 );
  389.    Td[3][1] = SCREEN_HEIGHT;
  390.    matrix_mult( Tw, 4, 4, Td, 4, 4, tmp );
  391.    copy_matrix( tmp, Tw, 4, 4 );
  392.    /* Now, Tw has the world to device/screen transformation matrix. */
  393.  
  394.    if ( proj == PARALLEL )
  395.    {
  396.       /* Beautiful!!!  Perform a single transformation of the image (for
  397.          parallel projection). */
  398.       printf( "Transforming, projecting and mapping the image onto screen.  " );
  399.       matrix_mult( Tm, 4, 4, Tw, 4, 4, tmp );
  400.       copy_matrix( tmp, Tm, 4, 4 );
  401.       show_matrix( Tm, 4, 4 );
  402.       transform_and_homogenize_image( image, tr_image, Tm );
  403.       printf( "Done.\n" );
  404.       printf( "Rendering the image.  " );
  405.       render_image( LEFT_EYE );        printf( "Done.\n" );
  406.    }
  407.    if ( proj == PERSPECTIVE )
  408.    {
  409.       printf( "Transforming, projecting, homogenizing and mapping the " );
  410.       printf( "Left image onto screen.  " );
  411.       matrix_mult( Tm, 4, 4, Left, 4, 4, tmp );
  412.       matrix_mult( tmp, 4, 4, Tw, 4, 4, Left );
  413.       printf( "Left eye transformation matrix.\n" );
  414.       show_matrix( Left, 4, 4 );
  415.       transform_and_homogenize_image( image, tr_image, Left );
  416.       printf( "Done.\n" );
  417.       printf( "Rendering the Left eye image.  " );
  418.       render_image( LEFT_EYE );        printf( "Done.\n" );
  419.  
  420.       printf( "Transforming, projecting, homogenizing and mapping the " );
  421.       printf( "Right image onto screen.  " );
  422.       matrix_mult( Tm, 4, 4, Right, 4, 4, tmp );
  423.       matrix_mult( tmp, 4, 4, Tw, 4, 4, Right );
  424.       /* Move the right eye view into the lower half of the buffer. */
  425.       set_to_identity( Tw, 4 );
  426.       Tw[3][1] = SCREEN_HEIGHT;                 /* move in device coord */
  427.       matrix_mult( Right, 4, 4, Tw, 4, 4, tmp );
  428.       copy_matrix( tmp, Right, 4, 4 );
  429.       printf( "Right eye transformation matrix.\n" );
  430.       show_matrix( Right, 4, 4 );
  431.       transform_and_homogenize_image( image, tr_image, Right );
  432.       printf( "Done.\n" );
  433.       dszom( &0, &512, &1 );                   /* look at the lower half */
  434.       printf( "Rendering the Right eye image.  " );
  435.       render_image( RIGHT_EYE );        printf( "Done.\n" );
  436.    }
  437. }
  438.  
  439. /*------------------------- MAIN ------------------------------------*/
  440. main( argc, argv )
  441. int argc;
  442. char **argv;
  443. {
  444.     register    i;
  445.     long int    j;
  446.     int         response, tmp;
  447.     BOOLEAN     done;
  448.     double  x_min, x_max, y_min, y_max, z_min, z_max;
  449.     double  x, y, z;
  450.     char  str[128];         /* a temporary string buffer */
  451.  
  452.     /* setup some defaults */
  453.     f_color = 255;
  454.     done = FALSE;
  455.     light_source.x = 0.0;  light_source.y = 0.0;  light_source.z = 1.0;
  456.     eye_pt.x = 0.0;   eye_pt.y = 0.0;   eye_pt.z = 260.0;
  457.     vpn.x = -(eye_pt.x);   vpn.y = -(eye_pt.y);  vpn.z = -(eye_pt.z);
  458.     vup.x = 0.0;   vup.y = 1.0;   vup.z = 0.0;
  459.     proj_plane = -1.0;
  460.  
  461.     /* A welcome message */
  462.     printf( "\n\n\n            STM Data Viewer.\n\n\n" );
  463.     printf( "            Created by Victor J. Duvanenko\n" );
  464.     printf( "                    11/05/90\n\n\n\n" );
  465.  
  466.     set_clip_volume( -250.0, 250.0,  -250.0, 250.0,  0.0, -500.0 );
  467.     set_viewport( 50.0, 562.0,  0.0, 512.0,  0.0, 512.0 );
  468.  
  469.     open_lex();
  470.     configure_lex();
  471.     dsbuff( &0 );               /* display and manipulate buffer 0 */
  472.  
  473.     while( !done )
  474.     {
  475.        fflush( stdin );
  476.        print_menu();
  477.        scanf( "%d", &response );
  478.        switch( response)
  479.        {
  480.           case 1: read_stm_database();   dsclr( &(-1) );
  481.                   set_clip_volume((double)min.x, (double)max.x, (double)min.y,
  482.                                   (double)max.y, (double)min.z, (double)max.z );
  483.                   display_stm_database();    break;
  484.           case 2: set_light_source();        break;
  485.           case 3: set_viewer_eye_pt();       break;
  486.           case 4: set_view_up_vector();      break;
  487.           case 5: dsclr( &(-1));
  488.                   make_composite_viewing_matrix( PARALLEL );
  489.                   display_3D_data( PARALLEL );   break;
  490.           case 6: dsclr( &(-1));
  491.                   make_composite_viewing_matrix( PERSPECTIVE );
  492.                   display_3D_data( PERSPECTIVE );   break;
  493.           case 7: set_per_projection_plane();   break;
  494.           case 8: printf( "Enter window limits.\n" );
  495.                   printf( "x_min x_max  y_min y_max  z_min z_max\n " );
  496.                   scanf( "%lf%lf%lf%lf%lf%lf", &x_min, &x_max,
  497.                             &y_min, &y_max, &z_min, &z_max );
  498.                   set_clip_volume( x_min, x_max, y_min, y_max, z_min,z_max);
  499.                   break;
  500.           case 9: printf( "Enter viewport limits.\n" );
  501.                   printf( "x_min x_max  y_min y_max  z_min z_max\n " );
  502.                   scanf( "%lf%lf%lf%lf%lf%lf", &x_min, &x_max,
  503.                             &y_min, &y_max, &z_min, &z_max );
  504.                   set_viewport( x_min, x_max, y_min, y_max,
  505.                                 z_min, z_max );
  506.                   break;
  507.           case 10: dsmov( &512, &640, &2, &1 );
  508.                    printf( "Type any number to stop the stereo display: " );
  509.                    scanf( "%d", &tmp );
  510.                    dszom( &0, &0, &1 );     /* back to one eye view */
  511.                    break;
  512.           case 26: done = TRUE;  break;
  513.           default :  printf( "Illegal choice.\n" );
  514.        }
  515.  
  516.        if ( done )   break;    /* leave without timing */
  517.     }
  518.     dscls();          /* close the communication channel to the LEX */
  519.     return(0);
  520. }
  521.